package com.sl.ms.scope.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.itheima.em.sdk.EagleMapTemplate;
import com.itheima.em.sdk.enums.ProviderEnum;
import com.itheima.em.sdk.vo.Coordinate;
import com.itheima.em.sdk.vo.GeoResult;
import com.mongodb.client.result.DeleteResult;

import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;

import com.sl.ms.scope.entity.ServiceScopeEntity;
import com.sl.ms.scope.enums.ServiceTypeEnum;
import com.sl.ms.scope.service.ScopeService;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
@Service
public class ScopeServiceImpl implements ScopeService {

    @Resource
    private EagleMapTemplate eagleMapTemplate;

    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * 新增或更新服务范围
     *
     * @param bid     业务id
     * @param type    类型
     * @param polygon 多边形坐标点
     * @return
     */
    @Override
    public Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon) {

        // polygon不用判空

        // 1.根据条件查询作业范围 bid  type
        Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode()));
        ServiceScopeEntity serviceScope = mongoTemplate.findOne(query, ServiceScopeEntity.class);


        if (ObjectUtil.isEmpty(serviceScope) || serviceScope == null) {
            serviceScope = new ServiceScopeEntity();
            // 不需要设置 让他自己自增就可以了
            // serviceScope.setId(new ObjectId());
            serviceScope.setBid(bid);
            serviceScope.setType(type.getCode());
            serviceScope.setPolygon(polygon);
            serviceScope.setCreated(System.currentTimeMillis());
            serviceScope.setUpdated(System.currentTimeMillis());
        } else {
            // 存在
            serviceScope.setPolygon(polygon);
            serviceScope.setUpdated(System.currentTimeMillis());

        }
        try {
            this.mongoTemplate.save(serviceScope);
            return true;
        } catch (Exception e) {
            log.error("新增/更新服务范围数据失败！ bid = {}, type = {}, points = {}", bid, type, polygon.getPoints(), e);
        }
        return false;


    }

    /**
     * 根据主键id删除数据
     *
     * @param id 主键
     * @return
     */
    @Override
    public Boolean delete(String id) {
        Query query = Query.query(Criteria.where("_id").is(new ObjectId(id)));
        DeleteResult remove = mongoTemplate.remove(query, ServiceScopeEntity.class);
        return remove.getDeletedCount() > 0;
    }

    /**
     * 根据业务id和类型删除数据
     *
     * @param bid  业务id
     * @param type 类型
     * @return
     */
    @Override
    public Boolean delete(Long bid, ServiceTypeEnum type) {
        Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode()));

        DeleteResult remove = mongoTemplate.remove(query, ServiceScopeEntity.class);
        return remove.getDeletedCount() > 0;
    }

    /**
     * 根据主键查询数据
     *
     * @param id 主键
     * @return
     */
    @Override
    public ServiceScopeEntity queryById(String id) {
        return this.mongoTemplate.findById(new ObjectId(id), ServiceScopeEntity.class);
    }

    /**
     * 根据业务id和类型查询数据
     *
     * @param bid  业务id
     * @param type 类型
     * @return
     */
    @Override
    public ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type) {
        Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //构造查询条件
        return this.mongoTemplate.findOne(query, ServiceScopeEntity.class);
    }

    /**
     * 根据坐标点查询所属的服务对象
     *
     * @param type  类型
     * @param point 坐标点
     * @return
     */
    @Override
    public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point) {

        // intersects 表示交集  也就是这个点是否在哪个里面
        Query query = Query.query(Criteria.where("polygon").intersects(point)
                .and("type").is(type.getCode()));

        return mongoTemplate.find(query, ServiceScopeEntity.class);
    }

    /**
     * 根据详细地址查询所属的服务对象
     *
     * @param type    类型
     * @param address 详细地址，如：北京市昌平区金燕龙办公楼传智教育总部
     * @return
     */
    @Override
    public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address) {
        // 1.先将address转为坐标点
        //根据详细地址查询坐标
        // 第一个参数是高德地图
        GeoResult geoResult = this.eagleMapTemplate.opsForBase().geoCode(ProviderEnum.AMAP, address, null);
        // 2.再来调用上面的方法
        Coordinate location = geoResult.getLocation();
        Query query = Query.query(Criteria.where("type").is(type.getCode()).and("polygon").intersects(new GeoJsonPoint(location.getLongitude(), location.getLatitude())));
        return mongoTemplate.find(query, ServiceScopeEntity.class);

    }
}
